﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Cemit.PolyServer
{
    /// <summary>
    /// 缓存堆，可记录一系列数据并返回一个序号，能够进行自动增长
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class BufferHeap<T> 
    {
        private readonly long increment;
        private readonly long maxSize;

        private T[] buffer;
        private long current;

        private Stack<long> freeIndexPool;


        public BufferHeap(long startSize, long increment, long maxSize)
        {
            this.increment = increment;
            this.maxSize = maxSize;

            CleanAndResetBuffer(startSize);
        }

        //重新分配缓冲池使用的缓冲区空间
        private void CleanAndResetBuffer(long size)
        {
            if (size > maxSize)
            {
                throw new Exception("超出最大空间限制！");
            }

            //创建一个大的缓冲区并将其分割
            //输出到每个SocketAsyncEventArg对象
            current = 0;
            buffer = new T[size];
            freeIndexPool = new Stack<long>();
        }

        public T Get(long index)
        {
            return buffer[index];
        }

        // 将缓冲池中的缓冲区分配给
        // 指定SocketAsyncEventArgs对象
        // <returns>如果缓冲区设置成功，则为true，否则为false</returns>
        public long Add(T obj)
        {
            //判断是否有已回收的池
            if (freeIndexPool.Count > 0)
            {
                long index = freeIndexPool.Pop();
                buffer[index] = obj;
                return index;
            }
            else
            {
                long index = current;

                if (index == buffer.Length)
                {
                    if (buffer.Length + increment > maxSize)
                    {
                        //总空间不足
                        throw new Exception("超出最大空间限制！");
                    }
                    else
                    {
                        T[] newBuff = new T[buffer.Length + increment];
                        Array.Copy(buffer, newBuff, buffer.Length);
                        buffer = newBuff;
                    }
                }

                buffer[index] = obj;
                current++;

                return index;
            }
        }

        // 从SocketAsyncEventArg对象中移除缓冲区。  
        // 这将缓冲区释放回缓冲池
        public void Free(long index)
        {
            freeIndexPool.Push(index);
        }
    }
}
